﻿// 读写锁.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include "pch.h"
#include <iostream>
#include <Windows.h>

/*
读写锁：
	读写锁是一种多线程并发控制机制，用于管理共享资源的访问。它允许多个线程同时读取共享资源，但只允许一个线程写入共享资源。读写锁可以提高系统的并发性能，因为多个线程可以同时读取共享资源而不会发生冲突。
	同时，通过限制写入操作的并发性，可以避免数据不一致性和竞态条件的问题。读写锁通常由两个锁组成：一个读锁和一个写锁。读锁可以由多个线程同时持有，但写锁只能由一个线程持有。
		原子锁什么都相斥	而读写锁 只有读和写之间相斥
	像是腾讯文档
		读 和 读  互相不影响
		读读相容 读写相斥

	1. 创建读写锁   SRWLock
			定义读写锁变量
	2. 初始化  InitializeSRWLock
	3. 使用
		3.1 加锁  使用前 加锁
			3.1.1 加读锁  AcquireSRWLockShared
			3.1.2 加写锁  AcquireSRWLockExclusive
		3.2 解锁  使用后 解锁
			3.2.1 解读锁  ReleaseSRWLockShared
			3.2.2 解写锁  ReleaseSRWLockExclusive

*/
#define ISF 1
#define ISFC 0


int n = 0;

SRWLOCK srwLock;


#if ISF
void f()
{
	for (int i = 0; i < 50000000; i++)
	{
		AcquireSRWLockExclusive(&srwLock);		//加写锁
		n++;
		ReleaseSRWLockExclusive(&srwLock);		//解写锁
	}
}
#endif


/*
	结果很明显	如果fc1和fc2用的都是相同的锁，那么他们是同时运行的	如果用的不是相同的锁，那就不是一同运行的，所以运行结果一般情况都是只打印fc1——————\n
*/
#if ISFC
void fc1()
{
	while (1)
	{
		AcquireSRWLockExclusive(&srwLock);		//加写锁
		printf("fc1——————\n");
		Sleep(1000);
		ReleaseSRWLockExclusive(&srwLock);		//解写锁
	}
}
void fc2()
{
	while (1)
	{
		AcquireSRWLockExclusive(&srwLock);		//加写锁
		printf("fc2==============\n");
		Sleep(1000);
		ReleaseSRWLockExclusive(&srwLock);		//解写锁
	}
}
#endif

int main()
{

	//初始化读写锁：
	InitializeSRWLock(&srwLock);



	//创建线程： 
#if ISF
	HANDLE h1 = CreateThread(NULL, NULL,
		(LPTHREAD_START_ROUTINE)f,
		NULL, NULL, NULL);
	HANDLE h2 = CreateThread(NULL, NULL,
		(LPTHREAD_START_ROUTINE)f,
		NULL, NULL, NULL);



	WaitForSingleObject(h1, INFINITE);
	WaitForSingleObject(h2, INFINITE);
#endif

#if ISFC
	HANDLE h1 = CreateThread(NULL, NULL,
		(LPTHREAD_START_ROUTINE)fc1,
		NULL, NULL, NULL);

	HANDLE h2 = CreateThread(NULL, NULL,
		(LPTHREAD_START_ROUTINE)fc2,
		NULL, NULL, NULL);



	WaitForSingleObject(h1, INFINITE);
	WaitForSingleObject(h2, INFINITE);
#endif

	printf("n:%d\n", n);        //没有任何方案的话，n最终的值不可能是100000000；


	return 0;
}


